package com.gopay.bis.citic.micro.impl;

import com.gopay.bis.citic.micro.operation.MicroPatCerHelper;
import com.gopay.bis.citic.micro.operation.XmlBeanUtil;
import com.gopay.bis.common.trace.PaymentLog;
import com.gopay.common.constants.bank.BankLogConstants;
import com.gopay.common.constants.proccode.ProcCodeConstants;
import com.gopay.common.domain.bank.BaseMessage;
import com.gopay.common.domain.bank.BisBankReturnVo;
import com.gopay.common.domain.bank.wechat.micro.req.*;
import com.gopay.common.domain.bank.wechat.micro.res.*;
import com.gopay.common.exception.GopayException;
import com.gopay.common.util.DateUtils;
import com.gopay.common.util.HttpsTransport;
import com.gopay.remote.bank.businesses.MicroPayService;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;

/**
 * 小额免密支付接口实现类
 * 
 * @ClassName: MicroPayBankServiceImpl
 * @author w_jiqing
 * @date 2017年5月24日 下午3:19:53
 */
public class MicroPayBankServiceImpl implements MicroPayService {

    private static Logger logger = LoggerFactory.getLogger(MicroPayBankServiceImpl.class);
    private MicroPatCerHelper microPayCerHelper;
    private HttpsTransport httpsTransport;

    private String kafkaSwitch;

    @Override
    public Object payment(BaseMessage baseMsg) throws GopayException {
        MicroPayResMsg payRes = new MicroPayResMsg();
        try {
            MicroPayReqMsg message = (MicroPayReqMsg) baseMsg;
            String payXml = microPayCerHelper.sign(message.getPlainMessage(), message.getPrivateKeyPath());
            logger.info("micro send swiftpass payment  xml :" + payXml);
            httpsTransport.setUrl(message.getPayUrl());
            Object res = httpsTransport.submit(payXml.getBytes());
            payRes = XmlBeanUtil.toBean((String) res, MicroPayResMsg.class);
            if (microPayCerHelper.isSuccessStatus(res)) {
                if ((boolean) microPayCerHelper.verify(res, message.getPrivateKeyPath())) {
                    payRes.setSuccess(true);
                } else {
                    throw new GopayException(ProcCodeConstants.PROC_CODE_100E7026);
                }
            }
            //保存到kafka中
            saveKafkaInfo(baseMsg, payRes, (String) res);
        } catch (Exception e) {
            logger.error("micro send swiftpass payment error ", e);
            throw new GopayException(ProcCodeConstants.PROC_CODE_100E7026);
        }
        return payRes;
    }

    @Override
    public Object queryOrder(BaseMessage baseMsg) throws GopayException {
        MicroQueryResMsg queryRes = new MicroQueryResMsg();
        try {
            MicroQueryReqMsg message = (MicroQueryReqMsg) baseMsg;
            String queryXml = microPayCerHelper.sign(message.getPlainMessage(), message.getPrivateKeyPath());
            logger.info("micro send swiftpass queryOrder  xml :" + queryXml);
            httpsTransport.setUrl(message.getQueryUrl());
            Object res = httpsTransport.submit(queryXml.getBytes());
            queryRes = XmlBeanUtil.toBean((String) res, MicroQueryResMsg.class);
            if (microPayCerHelper.isSuccessStatus(res)) {
                if ((boolean) microPayCerHelper.verify(res, message.getPrivateKeyPath())) {

                    queryRes.setSuccess(true);
                } else {
                    throw new GopayException(ProcCodeConstants.PROC_CODE_100E7026);
                }
            }
        } catch (Exception e) {
            logger.error("micro send swiftpass queryOrder error ", e);
            throw new GopayException(ProcCodeConstants.PROC_CODE_100E7026);
        }
        return queryRes;
    }

    @Override
    public Object reverse(BaseMessage msg) throws GopayException {
        MicroReverseResMsg reverseRes = new MicroReverseResMsg();
        try {
            MicroReverseReqMsg message = (MicroReverseReqMsg) msg;
            String reverseXml = microPayCerHelper.sign(message.getPlainMessage(), message.getPrivateKeyPath());
            logger.info("micro send swiftpass reverse  xml :" + reverseXml);
            httpsTransport.setUrl(message.getPayUrl());
            Object res = httpsTransport.submit(reverseXml.getBytes());
            reverseRes = XmlBeanUtil.toBean((String) res, MicroReverseResMsg.class);
            if (microPayCerHelper.isSuccessStatus(res)) {
                if ((boolean) microPayCerHelper.verify(res, message.getPrivateKeyPath())) {
                    reverseRes.setSuccess(true);
                } else {
                    throw new GopayException(ProcCodeConstants.PROC_CODE_100E7026);
                }
            }
        } catch (Exception e) {
            logger.error("micro send swiftpass reverse error ", e);
            throw new GopayException(ProcCodeConstants.PROC_CODE_100E7026);
        }
        return reverseRes;
    }

    @Override
    public Object refund(BaseMessage baseMsg) throws GopayException {
        MicroRefundResMsg refundRes = new MicroRefundResMsg();
        try {
            MicroRefundReqMsg message = (MicroRefundReqMsg) baseMsg;
            String rufundXml = microPayCerHelper.sign(message.getPlainMessage(), message.getPrivateKeyPath());
            logger.info("micro send swiftpass refund  xml :" + rufundXml);
            httpsTransport.setUrl(message.getPayUrl());
            Object res = httpsTransport.submit(rufundXml.getBytes());
            refundRes = XmlBeanUtil.toBean((String) res, MicroRefundResMsg.class);
            if (microPayCerHelper.isSuccessStatus(res)) {
                if ((boolean) microPayCerHelper.verify(res, message.getPrivateKeyPath())) {

                    refundRes.setSuccess(true);
                } else {
                    throw new GopayException(ProcCodeConstants.PROC_CODE_100E7026);
                }
            }
        } catch (Exception e) {
            logger.error("micro send swiftpass refund error ", e);
            throw new GopayException(ProcCodeConstants.PROC_CODE_100E7026);
        }
        return refundRes;
    }

    @Override
    public Object refundQuery(BaseMessage msg) throws GopayException {
        MicroRefundQueryResMsg refQueRes = new MicroRefundQueryResMsg();
        try {
            MicroRefundQueryReqMsg message = (MicroRefundQueryReqMsg) msg;
            String refQueXml = microPayCerHelper.sign(message.getPlainMessage(), message.getPrivateKeyPath());
            logger.info("send swiftpass refund  xml :" + refQueXml);
            httpsTransport.setUrl(message.getPayUrl());
            Object res = httpsTransport.submit(refQueXml.getBytes());
            if (microPayCerHelper.isSuccessStatus(res)) {
                if ((boolean) microPayCerHelper.verify(res, message.getPrivateKeyPath())) {
                    String refundBody = XmlBeanUtil.toRefundQueryXml((String) res);
                    refQueRes = XmlBeanUtil.toBean((String) refundBody, MicroRefundQueryResMsg.class);
                    if ("0".equals(refQueRes.getStatus()) && "0".equals(refQueRes.getResult_code())) {
                        int refund_count = Integer.valueOf(StringUtils.substringBetween((String) res,
                                "<refund_count><![CDATA[", "]]></refund_count>"));
                        if (refund_count > 0) {
                            refQueRes.setRefund_count(refund_count);
                            refQueRes.fillItem((String) res);

                        }
                    }
                    refQueRes.setSuccess(true);
                } else {
                    throw new GopayException(ProcCodeConstants.PROC_CODE_100E7026);
                }
            }
        } catch (Exception e) {
            logger.error("micro send swiftpass refundQuery error ", e);
            throw new GopayException(ProcCodeConstants.PROC_CODE_100E7026);
        }
        return refQueRes;
    }

    public MicroPatCerHelper getMicroPayCerHelper() {
        return microPayCerHelper;
    }

    public void setMicroPayCerHelper(MicroPatCerHelper microPayCerHelper) {
        this.microPayCerHelper = microPayCerHelper;
    }

    public HttpsTransport getHttpsTransport() {
        return httpsTransport;
    }

    public void setHttpsTransport(HttpsTransport httpsTransport) {
        this.httpsTransport = httpsTransport;
    }

    /**
     * hougn 2017-10-11保存到kafka中
     * @param baseMsg
     * @param resMessage
     * @param plainText
     * @throws IOException
     */
    private void saveKafkaInfo(BaseMessage baseMsg, MicroPayResMsg resMessage, String plainText) throws IOException {
        BisBankReturnVo vo = new BisBankReturnVo();
        //国付宝订单号
        vo.setGopayOrderId(baseMsg.getOrderId());
        //银行返回订单号
        vo.setBankOrderId(baseMsg.getBankOrderId());
        //银行渠道
        vo.setBankChannel(baseMsg.getBankIntrChann().value);
        //银行编码
        vo.setBankCode(BankLogConstants.BANK_LOG_CITIC_PAY_MICROPAY);
        //银行返回错误的xml文件信息
        vo.setBankReturnXml(plainText);
        //银行返回错误码
        vo.setRsCode(resMessage.getStatus());
        //银行返回的错误信息
        vo.setRsMsg(resMessage.getMessage());
        //银行报文订单返回时间
        vo.setBankReturnDate(DateUtils.getCurrDate("yyyy-MM-dd HH:mm:ss"));
        //报文返回记录日志时间  时间格式：yyyy-MM-dd HH:mm:ss
        vo.setCreateTsErr(DateUtils.getCurrDate("yyyy-MM-dd HH:mm:ss"));

        //保存到kafka中
        PaymentLog.info(vo,kafkaSwitch);
    }

    public String getKafkaSwitch() {
        return kafkaSwitch;
    }

    public void setKafkaSwitch(String kafkaSwitch) {
        this.kafkaSwitch = kafkaSwitch;
    }
}
